package com;


import com.message.RpcReqMessage;
import com.message.RpcRespMessage;
import com.message.factory.MessageDeSerializerFactory;
import com.message.factory.RpcMessageFactory;
import com.protocol.SharedMessageCodec;
import com.service.ServiceFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LoggingHandler;

import java.lang.reflect.Method;

/**
 * @author 罗俊华
 * @date 2021/9/1 - 4:24 下午
 */
public class RpcServer {

    public static void main(String[] args) {

        NioEventLoopGroup eventExecutors = new NioEventLoopGroup();

        LoggingHandler LOGGING_HANDLER = new LoggingHandler();

        SharedMessageCodec SHARED_MESSAGE_CODEC = new SharedMessageCodec(new RpcMessageFactory());

        new ServerBootstrap()
                .group(eventExecutors)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline().addLast(

                                new LengthFieldBasedFrameDecoder(1024, 11, 4),
                                SHARED_MESSAGE_CODEC,
                                LOGGING_HANDLER,
                                new SimpleChannelInboundHandler<RpcReqMessage>() {
                                    @Override
                                    protected void channelRead0(ChannelHandlerContext ctx, RpcReqMessage msg) throws Exception {

                                        RpcRespMessage rpcRespMessage = new RpcRespMessage();

                                        rpcRespMessage.setSequenceId(msg.getSequenceId());

                                        try {

                                            Object service = ServiceFactory.getService(msg.getInterfaceName());

                                            Method targetMethod = service.getClass().getMethod(msg.getTargetMethodName(), msg.getParameterTypes());

                                            Object result = targetMethod.invoke(service, msg.getArgs());

                                            rpcRespMessage.setResult(result);

                                        } catch (Exception e) {
                                            e.printStackTrace();
//                                            e 的异常堆栈信息太多，客户端拿到了也看不懂
                                            rpcRespMessage.setT(new RuntimeException("远程调用失败：" + e.getCause().getMessage()));
                                        }


                                        ctx.writeAndFlush(rpcRespMessage);
                                    }
                                }
                        );
                    }
                }).bind(10111);

    }

}
